#ifndef ZUC2_RINGBUFF_H
#define ZUC2_RINGBUFF_H
#include <mutex>

template <typename T> class RingBuff
{
public:
    RingBuff(size_t max)
    {
        m_size = max;
        m_free_size = max;
        m_buff = new T[max];
        m_out = m_in = 0;
    }
    ~RingBuff() { delete[] m_buff; }
    int push(const T& val)
    {
        std::lock_guard<std::mutex> l(m_mutex);
        m_buff[m_in] = val;
        if (m_in == m_size - 1)
        {
            m_in = 0;
        }
        else
        {
            m_in++;
        }
        if (m_free_size)
        {
            m_free_size--;
        }
        else
        {
            return -1;
        }
        return 0;
    }
    int pop(T& val)
    {
        std::lock_guard<std::mutex> l(m_mutex);
        if (m_free_size == m_size)
            return -1;
        val = m_buff[m_out];
        if (m_out == m_size - 1)
        {
            m_out = 0;
        }
        else
        {
            m_out++;
        }

        m_free_size++;
        return 0;
    }
    inline size_t size() const { return m_size - m_free_size; }

protected:
    T* m_buff;
    size_t m_size;
    size_t m_free_size;
    uint32_t m_in, m_out;
    std::mutex m_mutex;
};

#endif